package testtiles;

import java.util.HashMap;

import butines.core.game.Image;
import butines.core.game.ImageSheet;
import butines.game.Animation;

public class Resources {

	private Define define;
	
	private HashMap<String, Image> images = new HashMap<String, Image>();
	private HashMap<String, ImageSheet> sprites = new HashMap<String, ImageSheet>();
	private HashMap<String, Animation> animations = new HashMap<String, Animation>();
	private HashMap<String, UnitClass> unitClasses = new HashMap<String, UnitClass>();
	private HashMap<String, ImageSheet> tilesets = new HashMap<String, ImageSheet>();
	
	public Resources(String path) {
		if (path == null) {
			throw new IllegalArgumentException("Argument 'path' is null ");
		}
		define = new Define(path);
		define.load();
		loadResources();
	}
	
	public void addImage(Image image) {
		addImage(image.getPath(), image);
	}
	
	public void addImage(String name, Image image) {
		if (name == null) {
			throw new IllegalArgumentException("Argument 'name' is null");
		}
		if (image == null) {
			throw new IllegalArgumentException("Argument 'image' is null");
		}
		images.put(name, image);
	}
	
	public void addSprite(String name, ImageSheet sprite) {
		if (name == null) {
			throw new IllegalArgumentException("Argument 'name' is null");
		}
		if (sprite == null) {
			throw new IllegalArgumentException("Argument 'sprite' is null");
		}
		sprites.put(name, sprite);
	}
	
	public void addAnimation(String name, Animation animation) {
		if (name == null) {
			throw new IllegalArgumentException("Argument 'name' is null");
		}
		if (animation == null) {
			throw new IllegalArgumentException("Argument 'animation' is null");
		}
		animations.put(name, animation);
	}
	
	public void addTileset(String name, ImageSheet tileset) {
		if (name == null) {
			throw new IllegalArgumentException("Argument 'name' is null");
		}
		if (tileset == null) {
			throw new IllegalArgumentException("Argument 'tileset' is null");
		}
		tilesets.put(name, tileset);
	}
	
	public Image getImage(String name) {
		return images.get(name);
	}
	
	public ImageSheet getSprite(String name) {
		return sprites.get(name);
	}
	
	public Animation getAnimation(String name) {
		return animations.get(name);
	}
	
	public UnitClass getUnitClass(String name) {
		return unitClasses.get(name);
	}
	
	public ImageSheet getTileset(String name) {
		return tilesets.get(name);
	}
	
	@SuppressWarnings("unchecked")
	public <T> T get(String name) {
		if (name == null) {
			throw new IllegalArgumentException("Argument 'name' is null");
		}
		name = name.trim();
		if (images.containsKey(name)) {
			return (T)images.get(name);
		}
		if (sprites.containsKey(name)) {
			return (T)sprites.get(name);
		}
		if (animations.containsKey(name)) {
			return (T)animations.get(name);
		}
		return null;
	}
	
	private void parseImage(String name, String value) {
		addImage(name, new Image(value));
	}
	
	private void parseSprite(String name, String value) {
		String[] arr = value.split(",");
		
		Image image = getImage(arr[0].trim());
		int width = Integer.parseInt(arr[1].trim());
		int height = Integer.parseInt(arr[2].trim());
		int numAngles = Integer.parseInt(arr[3].trim());
				
		image = ImageHelper.createIsometricImage(image, numAngles);
		
		ImageSheet sprite = new ImageSheet(image, width, height);
		addSprite(name, sprite);
	}
	
	private void parseAnimation(String name, String value) {
		String[] arr = value.split(",");
		
		ImageSheet imageSheet = getSprite(arr[0].trim());
		int numAngles = Integer.parseInt(arr[1].trim());
		float duration = Float.parseFloat(arr[2].trim());
		boolean loop   = Boolean.parseBoolean(arr[3].trim());
		int[] frames = new int[arr.length - 4];
		
		for (int i = 4, j = 0; i < arr.length; i++, j++) {
			frames[j] = Integer.parseInt(arr[i].trim());
		}
		
		Animation animation = new Animation(imageSheet, numAngles, duration, frames);
		animation.setLoop(loop);
		
		addAnimation(name, animation);
	}
	
	private void parseTileset(String name, String value) {
		String[] arr = value.split(",");
		
		Image image = getImage(arr[0].trim());
		int width = Integer.parseInt(arr[1].trim());
		int height = Integer.parseInt(arr[2].trim());
				
		ImageSheet sprite = new ImageSheet(image, width, height);
		addTileset(name, sprite);
	}
	
	private void parseUnitClass(String namespace) {
		String className       = define.getValue(namespace + ".className", String.class);
		int    maxHealth       = define.getValue(namespace + ".maxHealth", Integer.class);
		float  maxSpeed        = define.getValue(namespace + ".maxSpeed", Float.class);
		float  viewDistance    = define.getValue(namespace + ".viewDistance", Float.class);
		float  radiusBounding  = define.getValue(namespace + ".radiusBounding", Float.class);
		int    armor           = define.getValue(namespace + ".armor", Integer.class);
		float  attackCooldown  = define.getValue(namespace + ".attackCooldown", Float.class);
		int    attackDamage    = define.getValue(namespace + ".attackDamage", Integer.class);
		float  attackRange     = define.getValue(namespace + ".attackRange", Float.class);
		String animationStay   = define.getValue(namespace + ".animation.stay", String.class);
		String animationWalk   = define.getValue(namespace + ".animation.walk", String.class);
		String animationAttack = define.getValue(namespace + ".animation.attack", String.class);
		String animationDie    = define.getValue(namespace + ".animation.die", String.class);

		UnitClass unitClass = new UnitClass();
		unitClass.setClassName(className);
		unitClass.setMaxHealth(maxHealth);
		unitClass.setMaxSpeed(maxSpeed);
		unitClass.setViewDistance(viewDistance);
		unitClass.setRadiusBounding(radiusBounding);
		unitClass.setArmor(armor);
		unitClass.setAttackCooldown(attackCooldown);
		unitClass.setAttackDamage(attackDamage);
		unitClass.setAttackRange(attackRange);
		unitClass.setStay(getAnimation(animationStay));
		unitClass.setWalk(getAnimation(animationWalk));
		unitClass.setAttack(getAnimation(animationAttack));
		unitClass.setDie(getAnimation(animationDie));
		
		unitClasses.put(namespace, unitClass);
	}
	
	private void loadResources() {
		
		for (String name: define.getImageAlias()) {
			String value = define.getProperty(name);
			name = (name == null) ? null : name.trim();
			value = (value == null) ? null : value.trim();
			parseImage(name, value);
		}
		
		for (String name: define.getSpriteAlias()) {
			String value = define.getProperty(name);
			name = (name == null) ? null : name.trim();
			value = (value == null) ? null : value.trim();
			parseSprite(name, value);
		}
		
		for (String name: define.getAnimationAlias()) {
			String value = define.getProperty(name);
			name = (name == null) ? null : name.trim();
			value = (value == null) ? null : value.trim();
			parseAnimation(name, value);
		}
		
		for (String namespace: define.getUnitClassAlias()) {
			parseUnitClass(namespace);
		}
		
		for (String name: define.getTilesetAlias()) {
			String value = define.getProperty(name);
			name = (name == null) ? null : name.trim();
			value = (value == null) ? null : value.trim();
			parseTileset(name, value);
		}
		
	}
	
	public void release() {
		images.clear();
		sprites.clear();
		animations.clear();
		unitClasses.clear();
		tilesets.clear();
		define.clear();
	}

}
